<?php
/**
 * 
 * Copyright (c) 2008 Jerry Jalava <jerry.jalava@gmail.com>
 * Licensed under the GPLv3 license
 * http://www.gnu.org/licenses/gpl.html
 * 
 */

class couchdb_replicator_http extends couchdb_replicator implements couchdb_replicator_interface
{    
    public function replicate()
    {
        $this->can_connect();
        
        $from_packet = json_encode(array(
            'source' => "http://{$this->configuration['source']['host']}:{$this->configuration['source']['port']}/{$this->configuration['source']['db']}",
            'target' => "http://{$this->configuration['target']['host']}:{$this->configuration['source']['port']}/{$this->configuration['target']['db']}",
        ));
                
        $transport = new couchdb_transport($this->local_configuration);
        
        try
        {
            $from_results = $transport->free_execute('_replicate', 'POST', $from_packet);
        }
        catch (couchdb_transport_exception $e)
        {
            throw new couchdb_replicator_exception("Unknown error occured while executing replication to {$this->configuration['target']['host']}. {$e}");
        }
        
        $to_results = false;
        
        if (   !isset($this->configuration['setup']['one_way'])
            || !$this->configuration['setup']['one_way'])
        {
            $to_packet = json_encode(array(
                'source' => "http://{$this->configuration['target']['host']}:{$this->configuration['source']['port']}/{$this->configuration['target']['db']}",
                'target' => "http://{$this->configuration['source']['host']}:{$this->configuration['source']['port']}/{$this->configuration['source']['db']}",
            ));
            
            try
            {
                $to_results = $transport->free_execute('_replicate', 'POST', $to_packet);
            }
            catch (couchdb_transport_exception $e)
            {
                throw new couchdb_replicator_exception("Unknown error occured while executing replication to {$this->configuration['source']['host']}. {$e}");
            }            
        }
        
        return array(
            'from' => $from_results,
            'to' => $to_results
        );
    }
    
    private function set_view($function)
    {
        //TODO: Implement
        /**
         * This will create temp db in sources and run the given temp view
         * and inserts the result to the created temp db.
         * After that those dbs are replicated to the original targets
        **/
        
        return;
    }
    
    public function check_config()
    {                
        if (! isset($this->configuration['source']['host']))
        {
            if (empty($this->local_configuration['host']))
            {
                throw new couchdb_replicator_exception('No source host found in configuration!');                
            }
            
            $this->configuration['source']['host'] = $this->local_configuration['host'];
        }
        
        if (! isset($this->configuration['source']['port']))
        {
            if (empty($this->local_configuration['port']))
            {
                throw new couchdb_replicator_exception('No source port found in configuration!');
            }
            
            $this->configuration['source']['port'] = $this->local_configuration['port'];
        }
        
        if (! isset($this->configuration['source']['db']))
        {
            throw new couchdb_replicator_exception('No source db found in configuration!');
        }

        if (! isset($this->configuration['target']['host']))
        {
            if (empty($this->local_configuration['host']))
            {
                throw new couchdb_replicator_exception('No target host found in configuration!');
            }
            
            $this->configuration['target']['host'] = $this->local_configuration['host'];
        }
        
        if (! isset($this->configuration['target']['port']))
        {
            if (empty($this->local_configuration['port']))
            {
                throw new couchdb_replicator_exception('No target port found in configuration!');
            }
            
            $this->configuration['target']['port'] = $this->local_configuration['port'];
        }
        
        if (! isset($this->configuration['target']['db']))
        {
            throw new couchdb_replicator_exception('No target db found in configuration!');
        }
        
        if (! isset($this->configuration['setup']))
        {
            $this->configuration['setup'] = array(
                'one_way' => false
            );
        }
        
        return true;
    }
    
    private function can_connect()
    {
        $source_socket = @fsockopen($this->configuration['source']['host'], $this->configuration['source']['port'], $errno = -1, $errstr = '', $timeout = 10);
        
        if (! $source_socket)
        {
            throw new couchdb_replicator_exception("Couldn't connect to source server at {$this->configuration['source']['host']}:{$this->configuration['source']['port']}");
        }
        
        @fclose($source_socket);
        
        $target_socket = @fsockopen($this->configuration['target']['host'], $this->configuration['target']['port'], $errno = -1, $errstr = '', $timeout = 20);
        
        if (! $target_socket)
        {
            throw new couchdb_replicator_exception("Couldn't connect to target server at {$this->configuration['target']['host']}:{$this->configuration['target']['port']}");
        }
        
        @fclose($target_socket);
        
        return true;
    }
}

?>